package com.amt.olcacon.controller.impact;

import com.amt.olcacon.db.DerbyConfig;
import com.amt.olcacon.entity.ImpactLinkEntity;
import com.amt.olcacon.entity.ImpactMethodEntity;
import com.amt.olcacon.mapper.ImpactLinkMapper;
import com.amt.olcacon.mapper.ImpactMethodMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.openlca.core.DataDir;
import org.openlca.core.database.CategoryDao;
import org.openlca.core.database.ImpactCategoryDao;
import org.openlca.core.database.ImpactMethodDao;
import org.openlca.core.model.ImpactMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @Author: yangyusheng
 * @Date: 2025/05/28
 */
@Slf4j
@RestController
@RequestMapping("impact")
public class ImpactController {

    private final ImpactMethodMapper impactMethodMapper;
    private final ImpactLinkMapper impactLinkMapper;

    public ImpactController(ImpactMethodMapper impactMethodMapper,
                            ImpactLinkMapper impactLinkMapper) {
        this.impactMethodMapper = impactMethodMapper;
        this.impactLinkMapper = impactLinkMapper;
    }

    /**
     * 计算接口
     *
     * @param name             ImpactMethod name
     * @param description      ImpactMethod description
     * @param impactCategories ImpactMethod categories
     * @return ImpactMethodId after insert
     */
    @GetMapping("/addImpactMethod")
    public Long addImpactMethod(
            @RequestParam("name") String name,
            @RequestParam("description") String description,
            @RequestParam("impactCategories") List<Long> impactCategories
    ) {

        try (var db = DataDir.get().openDatabase(DerbyConfig.DBNAME)) {

            // 插入 Derby
            ImpactMethod impactMethod = ImpactMethod.of(name);
            impactMethod.description = description;
            impactMethod.category = new CategoryDao(db).getForId(10086L);
            impactCategories.forEach(impactCategory -> impactMethod.add(new ImpactCategoryDao(db).getForId(impactCategory)));
            ImpactMethod impactMethodAfterInsert = new ImpactMethodDao(db).insert(impactMethod);
            Long impactMethodId = impactMethodAfterInsert.id;
            db.close();

            // 插入 MySQL ：tbl_impact_methods
            ImpactMethodEntity entity = new ImpactMethodEntity();
            entity.setId(impactMethodId);
            entity.setFCategory(10086L);
            entity.setRefId(impactMethodAfterInsert.refId);
            entity.setName(impactMethodAfterInsert.name);
            entity.setVersion(impactMethodAfterInsert.version);
            entity.setLastChange(impactMethodAfterInsert.lastChange);
            entity.setFCategory(
                    impactMethodAfterInsert.category != null ? impactMethodAfterInsert.category.id : null
            );
            entity.setTags(impactMethodAfterInsert. tags != null ? String.join(",", impactMethodAfterInsert.tags) : null);
            entity.setLibrary(impactMethodAfterInsert.library);
            entity.setDescription(impactMethodAfterInsert.description);
            entity.setOtherProperties(null);
            entity.setCode(impactMethodAfterInsert.code);
            entity.setFSource(
                    impactMethodAfterInsert.source != null ? impactMethodAfterInsert.source.id : null
            );

            impactMethodMapper.insert(entity);
            log.info("已插入 MySQL 表 tbl_impact_methods，ID={}", impactMethodId);

            // 插入 MySQL :tbl_impact_links
            for (Long impactCategory : impactCategories) {
                ImpactLinkEntity link = new ImpactLinkEntity();
                link.setFImpactMethod(impactMethodId);
                link.setFImpactCategory(impactCategory);
                impactLinkMapper.insert(link);
                log.info("插入 MySQL 中间表 tbl_impact_links 完成: impactMethodId={}, categories={}", impactMethodId, impactCategories);
            }

            return impactMethodId;
        } catch (Exception e) {
            log.error("addImpactMethod fail:", e);
            return 0L;
        }
    }

    /**
     * 根据ID删除ImpactMethod及其关联关系
     *
     * @param impactMethodId 要删除的ImpactMethod的ID
     * @return 删除成功返回true，否则返回false
     */
    @GetMapping("/deleteImpactMethod")
    public boolean deleteImpactMethod(@RequestParam("id") Long impactMethodId) {
        try (var db = DataDir.get().openDatabase(DerbyConfig.DBNAME)) {
            // 1. 先从MySQL删除关联记录 (tbl_impact_links)
            QueryWrapper<ImpactLinkEntity> linkWrapper = new QueryWrapper<>();
            linkWrapper.eq("F_IMPACT_METHOD", impactMethodId);
            int linkDeleteCount = impactLinkMapper.delete(linkWrapper); // MP: 根据条件删除
            log.info("已从 MySQL 中间表删除 {} 条关联记录", linkDeleteCount);

            // 2. 从MySQL删除主记录 (tbl_impact_methods)
            int mysqlDeleteCount = impactMethodMapper.deleteById(impactMethodId);
            if (mysqlDeleteCount > 0) {
                log.info("已从MySQL表tbl_impact_methods删除ImpactMethod ID={}", impactMethodId);
            }

            // 3. 从Derby删除记录
            ImpactMethodDao impactMethodDao = new ImpactMethodDao(db);
            ImpactMethod methodToDelete = impactMethodDao.getForId(impactMethodId);

            if (methodToDelete != null) {
                impactMethodDao.delete(methodToDelete);
                log.info("已从Derby数据库删除ImpactMethod ID={}", impactMethodId);
            } else {
                log.warn("Derby数据库中未找到ID={}的ImpactMethod", impactMethodId);
            }
            return true;
        } catch (Exception e) {
            log.error("删除ImpactMethod ID={} 失败:", impactMethodId, e);
            return false;
        }
    }

    /**
     * 更新ImpactMethod信息
     *
     * @param impactMethodId 要更新的ImpactMethod的ID
     * @param name           新的名称
     * @return 更新后的ImpactMethod ID
     */
    @GetMapping("/updateImpactMethod")
    public Long updateImpactMethod(
            @RequestParam("id") Long impactMethodId,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "description", required = false) String description
    ) {

        try (var db = DataDir.get().openDatabase(DerbyConfig.DBNAME)) {
            ImpactMethodDao impactMethodDao = new ImpactMethodDao(db);

            // 1. 从Derby获取现有记录
            ImpactMethod existingMethod = impactMethodDao.getForId(impactMethodId);
            if (existingMethod == null) {
                throw new RuntimeException("在Derby数据库中未找到ID=" + impactMethodId + "的ImpactMethod");
            }

            // 2. 更新Derby中的记录
            existingMethod.name = name;
            existingMethod.description = description;
            impactMethodDao.update(existingMethod);
            log.info("Derby数据库中的ImpactMethod ID={} 已更新", impactMethodId);


            // 3. 更新MySQL中的记录 (tbl_impact_methods)
            ImpactMethodEntity entity = new ImpactMethodEntity();
            entity.setId(impactMethodId);
            entity.setName(name);
            entity.setDescription(description);

            impactMethodMapper.updateById(entity);
            log.info("MySQL表tbl_impact_methods中的ImpactMethod ID={} 已更新", impactMethodId);

        } catch (Exception e) {
            log.error("更新ImpactMethod ID={} 失败:", impactMethodId, e);
        }
        return impactMethodId;
    }

}
